<?php

namespace Libraries;

class Tree {
	//private $formatList = array();
	function __construct(){
		
	}
	
	/**
	 * 得到父级数组
	 * @return $newArr: Array ( [id] => 1 [pid] => 0 [title] => 顶级栏目一 )
	 */
	public function getParent($theId,$treeArr){
		$newArr=array();
		$parentId=$this->getParentId($theId,$treeArr);
		if ($parentId != -1){	//	能取得父目录时
			foreach ($treeArr as $key=>$value){
				if ($value['id']==$parentId){
					$newArr=$value;
				}
			}
		}
		return $newArr;
	}
	
	/**
	 * 返回父ID字符串,比如：'12'
	 */
	public function getParentId($theId,$treeArr){
		$parentId = -1;	//	初始化赋值 -1
		foreach ($treeArr as $key=>$value){
			if ($value['id']==$theId){
				$parentId=$value['pid'];
			}
		}
		return $parentId;
	}
	
	/**
	 * 得到父级数组,父级的父级,直到最高级父目录
	 */
	public function getParents($theId,$treeArr){
		$newArr=array();
		foreach ($treeArr as $key=>$value){
			if ($value['id']==$theId){
				$newArr[$value['id']]=$value;	//取得自身的值
			}
		}
		$data=$this->getParent($theId,$treeArr);
		if (count($data)!=0){
			$newArr[$data['id']]=$data;
			$newArr=$this->getParents($data['id'],$treeArr)+$newArr;	//$newArr=$newArr+$this->getParents($data['id'],$treeArr);注意顺序，父目录排序，最高级靠前显示
		}
		return $newArr;
	}

	/**
	 * @param $theId
	 * @param $treeArr
	 * return 父级Id组合: 0,3,8 (8为父级Id)
	 */
	public function getParentIds($theId,$treeArr){
		$parentIds = 0;
		$data = $this->getParentId($theId,$treeArr);
		if ($data != -1 and $data != 0){
			$parentIds = $data;
			$parentIds = $this->getParentIds($data,$treeArr).','.$data;
		}
		return $parentIds;
	}

	/**
	 * @param $theId
	 * @param $treeArr
	 * return 父级Id和自身Id组合: 0,3,8 (8为自身Id)
	 */
	public function getParentIdsAndSelfId($theId,$treeArr){
		$parentIds = 0;
		$parentsArr = $this->getParents($theId,$treeArr);
		foreach ($parentsArr as $value){
			$parentIds .= ','.$value['id'];	// echo: 0,3,8
		}
		return $parentIds;
	}
	
	/**
	 * 得到子级数组
	 * @return $newArr: Array (
		 * 				[0] => Array ( [id] => 6 [pid] => 5 [name] => 三级栏目一 )
		 * 				[1] => Array ( [id] => 7 [pid] => 5 [name] => 三级栏目二 )
		 * 				[2] => Array ( [id] => 8 [pid] => 5 [name] => 三级栏目三 )
		 * 				[3] => Array ( [id] => 9 [pid] => 5 [name] => 三级栏目四 ) )
	 */
	public function getChild($theId,$treeArr){
		$newArr=array();
		if (is_array($treeArr)){
			foreach ($treeArr as $key=>$value){
				if ($value['pid']==$theId){
					//$newArr[$key]=$value;
					$newArr[]=$value;
				}
			}
		}
		//return $newArr?$newArr:false;
		return $newArr;
	}
	
	/**
	 * 取得theId下面所有的子栏目id，以数组形式输出
	 */
	public function getChildrenId($theId=0,$treeArr){
    	$newArr=array();
    	foreach ($treeArr as $key=>$value){
    		if ($value['pid']==$theId){
    			//$newArr[]=$value['id']; 会出错，未找到原因，所以改为如下用$key
				$newArr[$key]=$value['id'];
				$newArr=$newArr+$this->getChildrenId($value['id'],$treeArr);
			}
    	}
    	return $newArr;
    }
	
	/**
	 * 得到树型结构
	 * @param $theId	表示获得这个Id下的所有子级，0表示获得所有栏目
	 * @param $treeArr	初始待处理的二维数组
	 * @param $loopStr	生成树型结构的基本代码，例如:'<option value=$id $selected>$space$name</option>',其中$id,$name相当于数据表里面的字段名称
	 * @param $selectedId	被选中的Id，比如在做树型下拉框的时候需要用到
	 * @param $icon	树型结构区分父级和子级的标志,有几级子级，就循环几次$icon
	 * @param $selectedTag	替换选中栏目的$selected变量字符串
	 * @param $tab	默认即可，不用修改
	 */
	public function getTreeList($theId=0,$treeArr,$loopStr,$selectedId=0,$spaceTag='&nbsp;&nbsp;&nbsp;&nbsp;',$selectedTag='selected',$tab=0){
		$treeListStr = '';
		foreach ($treeArr as $key=>$value){
			if ($value['pid']==$theId){		//父亲找到儿子
				$selected = $value['id']==$selectedId?$selectedTag:'';
				$space = str_repeat($spaceTag,$tab);
				@extract($value);				//将数组中的key转化为变量名，value转化为变量值
				eval("\$nstr = \"$loopStr\";");	//替换$loopStr字符串中的变量
				//$treeListStr .= str_repeat($icon,$tab).$nstr."\n";
				$treeListStr .= $nstr."\n";
				$treeListStr .= $this->getTreeList($value['id'],$treeArr,$loopStr,$selectedId,$spaceTag,$selectedTag,$tab+1);
			}
		}
		return $treeListStr;
	}
	
	/**
	 * 同一方法，允许多选
	 * @param $selectedId='1,2,3' 被选中的Id参数调用
	 */
	public function getTreeListMulti($theId=0,$treeArr,$loopStr,$selectedId='0',$icon='&nbsp;&nbsp;',$selectedTag='selected',$tab=0){
		$treeListStr = '';
		foreach ($treeArr as $key=>$value){
			if ($value['pid']==$theId){
				//$selected = $value['id']==$selectedId?$selectedTag:'';
				$selected = $this->have($selectedId,$value['id'])?$selectedTag:'';
				@extract($value);
				eval("\$nstr = \"$loopStr\";");
				$treeListStr .= str_repeat($icon,$tab).$nstr."\n";
				$treeListStr .= $this->getTreeListMulti($value['id'],$treeArr,$loopStr,$selectedId,$icon,$selectedTag,$tab+1);
			}
		}
		return $treeListStr;
	}
	
	/**
	 * $selectedId='1,2,3' => ,,1,2,3,
	 * $valueId='2' => ,2,
	 */
	private function have($selectedId,$valueId){
		return strpos(',,'.$selectedId.',',','.$valueId.',');
	}
	
	/**
	 * 格式化数组
	 */
	public function getTreeArr($theId,$treeArr){
		$newArr=array();
		foreach ($treeArr as $key=>$value){
			if ($value['pid']==$theId){
				$newArr[$key]=$value;
				$newArr=$newArr+$this->getTreeArr($value['id'],$treeArr);
			}
		}
		return $newArr;
	}
	
	/**
	 * 返回带有前缀缩进格式的数组，完整的缩进主键名为['fullname']
	 */
	private function _getListArr($theId,$treeArr,$fields,$space,$icon){
		$children=$this->getChild($theId,$treeArr);	
		//下级分类的数组,如果没下级分类,结束递归
		if (!($n=count($children))){
			return;
		}
		$m=1;
		//循环所有的下级分类
		for ($i=0;$i<$n;$i++){
			$pre="";
			$pad="";
			if ($n==$m){
				$pre=$icon[2];
			}else {
				$pre=$icon[1];
				$pad=$space?$icon[0]:"";
			}
			if ($fields[1]==''){
				$children[$i]['fullname']=($space?$space.$pre:""); //fullName只起array('│', '├ ', '└ ')作用时，省掉后面跟标题内容
			}else {
				$children[$i]['fullname']=($space?$space.$pre:"").$children[$i][$fields[1]];
			}
			$this->formatList[]=$children[$i];
			$this->_getListArr($children[$i]['id'],$treeArr,$fields,$space.$pad."&nbsp;&nbsp;",$icon);	//递归下一级分类
			$m++;
		}
	}	
	public function getListArr($theId=0,$treeArr,$fields=array('parentId','title'),$space="",$icon=array('│', '├ ', '└ ')){
		unset($this->formatList);
		$this->_getListArr($theId,$treeArr,$fields,$space,$icon);
		return $this->formatList;
	}
	
	/**
	 * 返回同级目录数组，含自身,即同一个父目录的兄弟栏目
	 */
	public function getBrothers($theId,$treeArr){
		$newArr=array();
		$parentId=$this->getParentId($theId,$treeArr);
		return $this->getChild($parentId,$treeArr);
	}
	
	/**
	 * 返回给定数组中，给定Id的数组（自身数组）
	 */
	public function getSelf($theId,$treeArr){
		$newArr=array();
		foreach ($treeArr as $key=>$value){
			if ($value['id']==$theId){
				$newArr=$value;
			}
		}
		return $newArr;
	}
    
}
